import time
import uuid

from flask import request
from sqlalchemy import func, desc, asc

from constant.BlogConstant import BlogConstant
from entity.models import db, Article, Page, Archive
from service.LabelRecordService import save_article_labels, get_label_uuid_by_article_uuid, \
    get_label_uuid_by_article_uuid_and_label_uuid
from service.LabelService import get_label_by_label_name, create_new_label, get_label_by_uuid
from service.UploadService import save_file_to_oss
from settings import Setting
from util.FileUtil import create_file_with_path, get_file_content
from util.LoginUtil import get_login_info


def get_article_page(page):
    if page == '' or page is None:
        page = 0
    total = db.session.query(func.count(Article.uuid)).scalar()
    elements = db.session.query(Article).filter(Article.group_id != BlogConstant.about_group_id).order_by(
        Article.create_at.desc()).limit(BlogConstant.page_size).offset(
        (page - 1) * BlogConstant.page_size)
    db.session.close()
    elements = list(elements)
    return Page(page, BlogConstant.page_size, total, elements)


def get_article_page_by_publish(page):
    total = db.session.query(func.count(Article.uuid)).filter(Article.status == BlogConstant.publish_status).scalar()
    elements = db.session.query(Article).filter(Article.status == BlogConstant.publish_status).order_by(
        Article.create_at.desc()).limit(BlogConstant.page_size).offset(
        (page - 1) * BlogConstant.page_size)
    db.session.close()
    elements = list(elements)
    return Page(page, BlogConstant.page_size, total, elements)


def get_service_article_by_uuid(uuid):
    article = db.session.query(Article).filter(Article.uuid == uuid).first()
    label_records = get_label_uuid_by_article_uuid(uuid)
    labels = []
    for i in range(len(label_records)):
        labels.append(get_label_by_uuid(label_records[i].label_uuid)[0])
    article.labels = labels
    update_article_view_comment(article)
    return article


def update_article_view_comment(article):
    article.view_count = article.view_count + 1
    db.session.add(article)
    db.session.commit()


def update_article_comment_count(article):
    if article is not None:
        article.comment_count = article.comment_count + 1
        db.session.add(article)
        db.session.commit()


def save_article(article):
    db.session.add(article)
    db.session.commit()
    db.session.close()


def update_article(article):
    new_article = db.session.query(Article).filter(Article.uuid == article.uuid).first()
    new_article.status = article.status
    new_article.title = article.title
    new_article.summary = article.summary
    new_article.is_comment = article.is_comment
    new_article.pic_url = article.pic_url
    new_article.group_id = article.group_id
    new_article.is_draft = article.is_draft
    new_article.update_at = article.update_at
    new_article.document_type = article.document_type
    new_article.update_times = article.update_times + 1
    db.session.commit()
    db.session.close()


def assemble_article_by_request():
    article = Article()
    user = get_login_info()["user"]
    username = user['username']
    document_type = request.json['document_type']
    app_path = Setting.app_path
    create_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    archive = time.strftime("%Y-%m", time.localtime())
    article_id = uuid.uuid4()
    suffix = BlogConstant.document_html_type
    if document_type == BlogConstant.document_markdown_type:
        suffix = "md"
    path = "{}/resources/user/{}/article/{}/{}.{}".format(app_path, username, create_date, article_id, suffix)
    relative_path = "resources/user/{}/article/{}/{}.{}".format(username, create_date, article_id, suffix)
    article.uuid = article_id
    article.content_url = relative_path
    article.create_at = create_date
    article.create_by = user['uuid']
    article.update_at = create_date
    article.update_by = user['uuid']
    article.document_type = document_type
    article.view_count = 0
    article.archive = archive
    # status  [pending]   [delete]  [publish]
    article.status = BlogConstant.pending_status
    article.content = request.json['content']
    article.title = request.json['title']
    article.comment_count = 0
    article.view_count = 0
    article.update_times = 0
    article.summary = request.json['summary']
    article.is_comment = request.json['is_comment']
    article.pic_url = request.json['pic_url']
    article.group_id = request.json['group_id']
    article.is_draft = request.json['is_draft']
    # deal with labels
    for label_name in request.json['labels']:
        label = get_label_by_label_name(label_name)
        # label is not exist
        if len(label) == 0:
            # add label
            label_uuid = create_new_label(label_name, article.create_by)
            # add label to label record
            save_article_labels(label_uuid, article.uuid)
        # label is exist
        else:
            save_article_labels(label[0].uuid, article.uuid)
    create_file_with_path(path, article.content)
    save_file_to_oss(path, relative_path)
    return article


def delete_article(uuid, page):
    article = db.session.query(Article).filter(Article.uuid == uuid).first()
    article.status = BlogConstant.delete_status
    db.session.commit()
    return get_article_page(page)


def publish_article(uuid, page):
    article = db.session.query(Article).filter(Article.uuid == uuid).first()
    article.status = BlogConstant.publish_status
    db.session.commit()
    return get_article_page(page)


def top_article(uuid, page):
    article = db.session.query(Article).filter(Article.uuid == uuid).first()
    article.is_top = True
    db.session.commit()
    return get_article_page(page)


def assemble_edit_article_by_request():
    article = Article()
    article1 = get_service_article_by_uuid(request.json['uuid'])
    user = get_login_info()["user"]
    username = user['username']
    document_type = request.json['document_type']
    app_path = Setting.app_path
    update_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    article_id = article1.uuid
    suffix = BlogConstant.document_html_type
    create_at = str(article1.create_at).split(" ")[0]
    if document_type == BlogConstant.document_markdown_type:
        suffix = "md"
    path = "{}/resources/user/{}/article/{}/{}.{}".format(app_path, username, create_at, article_id, suffix)
    relative_path = "resources/user/{}/article/{}/{}.{}".format(username, create_at, article_id, suffix)
    article.uuid = article_id
    article.content_url = relative_path
    article.create_at = article1.create_at
    article.create_by = user['uuid']
    article.update_at = update_date
    article.update_by = user['uuid']
    article.document_type = document_type
    article.view_count = article1.view_count
    # status  [pending]   [delete]  [publish]
    article.status = article1.status
    article.update_times = article1.update_times
    article.content = request.json['content']
    article.title = request.json['title']
    article.comment_count = article1.comment_count
    article.view_count = article1.view_count
    article.summary = request.json['summary']
    article.is_comment = request.json['is_comment']
    pic_url = request.json['pic_url']
    if pic_url is None or pic_url == '':
        article.pic_url = article1.pic_url
    else:
        article.pic_url = pic_url
    article.group_id = request.json['group_id']
    article.is_draft = request.json['is_draft']
    # deal with labels
    for label_name in request.json['labels']:
        label = get_label_by_label_name(label_name)
        # label is not exist
        if len(label) == 0:
            # add label
            label_uuid = create_new_label(label_name, article.create_by)
            # add label to label record
            save_article_labels(label_uuid, article.uuid)
        # label is exist
        else:
            label_record = get_label_uuid_by_article_uuid_and_label_uuid(article.uuid, label[0].uuid)
            if label_record is None:
                save_article_labels(label[0].uuid, article.uuid)
    create_file_with_path(path, article.content)
    save_file_to_oss(path, relative_path)
    return article


def get_article_group_by_month():
    archives = []
    result = db.session.query(func.count(Article.uuid), Article.archive).filter(
        Article.status == BlogConstant.publish_status) \
        .group_by(Article.archive) \
        .order_by(desc(Article.archive)).all()
    for index in range(len(result)):
        article = db.session.query(Article).filter(Article.archive == result[index][1]) \
            .filter(Article.status == BlogConstant.publish_status).order_by(asc(Article.create_at)).all()
        archive = Archive(result[index][0], article, result[index][1])
        archives.append(archive)
    return archives


def get_about_by_group_id_is_about():
    return db.session.query(Article).filter(Article.group_id == BlogConstant.about_group_id).first()


def assemble_about_me():
    article = Article()
    article1 = get_service_article_by_uuid(request.json['uuid'])
    user = get_login_info()["user"]
    username = user['username']
    document_type = request.json['document_type']
    app_path = Setting.app_path
    update_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    article_id = article1.uuid
    suffix = BlogConstant.document_html_type
    create_at = str(article1.create_at).split(" ")[0]
    if document_type == BlogConstant.document_markdown_type:
        suffix = "md"
    path = "{}/resources/user/{}/article/{}/{}.{}".format(app_path, username, create_at, article_id, suffix)
    relative_path = "resources/user/{}/article/{}/{}.{}".format(username, create_at, article_id, suffix)
    article.uuid = article_id
    article.content_url = relative_path
    article.create_at = article1.create_at
    article.create_by = user['uuid']
    article.update_at = update_date
    article.update_by = user['uuid']
    article.document_type = document_type
    article.view_count = article1.view_count
    # status  [pending]   [delete]  [publish]
    article.status = article1.status
    article.update_times = article1.update_times
    article.content = request.json['content']
    pic_url = request.json['pic_url']
    if pic_url is None or pic_url == '':
        article.pic_url = article1.pic_url
    else:
        article.pic_url = pic_url
    article.comment_count = article1.comment_count
    article.view_count = article1.view_count
    create_file_with_path(path, article.content)
    save_file_to_oss(path, relative_path)
    return article


def update_about_me(article):
    new_article = db.session.query(Article).filter(Article.uuid == article.uuid).first()
    new_article.is_comment = article.is_comment
    new_article.document_type = article.document_type
    new_article.pic_url = article.pic_url
    new_article.update_times = article.update_times + 1
    db.session.commit()
    db.session.close()


def get_article_content(article):
    if article.content_url:
        content = get_file_content(article.content_url)
    else:
        base_path = Setting.app_path
        create_time = str(article.create_at).split(' ')[0]
        suffix = 'html'
        if article.document_type == 'markdown':
            suffix = "md"
        path = "{}/resources/user/{}/article/{}/{}.{}".format(base_path, article.create_by, create_time, article.uuid,
                                                              suffix)
        content = get_file_content(path)
    return content
